<!--
 * @Author: WangShuai 1830773767@qq.com
 * @Date: 2025-05-31 09:23:24
 * @LastEditors: WangShuai 1830773767@qq.com
 * @LastEditTime: 2025-07-04 08:32:10
 * @FilePath: \guanggu_traffic\src\views\traffic\components\EventManage\SearchResult.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
	<el-dialog
		v-model="dialogOverflowVisible"
		width="800px"
		draggable
		overflow
		:modal="false"
		@close="handleClose"
	>
		<!-- 自定义头部 -->
		<template #header>
			<div class="my-header">
				<el-button type="primary" @click="addHeatMap"
					>查看热力图</el-button
				>
				<el-button type="primary" @click="changeOpenChart"
					>查看统计图</el-button
				>
				<el-button type="primary" @click="exportExcel"
					>导出excel表</el-button
				>
			</div>
		</template>
		<!-- 统计图,导出excel表 -->
		<el-dialog
			v-model="openChartValue"
			append-to-body
			width="850px"
			draggable
			overflow
		>
			<!-- 自定义头部 -->
			<template #header>
				<div class="my-header">
					<!-- <span>事件统计图</span> -->
					<el-button type="success" @click="changeLine"
						>按月份统计</el-button
					>
					<el-button type="success" @click="changePie"
						>按类型统计</el-button
					>
				</div>
			</template>
			<br />
			<!-- 统计图(堆叠折线图和扇形图) -->
			<v-chart
				class="chart"
				:option="optionStackedLine"
				v-if="isShowLine"
			></v-chart>
			<v-chart
				class="chart"
				:option="optionPie"
				v-if="isShowPie"
			></v-chart>
		</el-dialog>
		<!-- 查询结果表格 
          :data="tableData" 绑定了表格的数据源;
          label是表格的列名;
          prop是数据源的key值;
          show-overflow-tooltip:当内容太长时,不换行,溢出工具提示;
    -->
		<el-table
			:data="tableData"
			style="width: 100%"
			highlight-current-row="true"
		>
			<el-table-column prop="事件编号" label="事件编号" width="150">
				<!-- 点击事件编号列可以触发函数,这里需要通过默认带的插槽实现,因为el-table-column不是真实的元素,无法点击,无法@click -->
				<template #default="scope">
					<div @click="flyToPoint(scope.row.事件编号)">
						{{ scope.row.事件编号 }}
					</div>
				</template>
			</el-table-column>
			<el-table-column prop="事件类型" label="事件类型" width="80px" />
			<el-table-column prop="事件等级" label="事件等级" />
			<el-table-column
				prop="发生时间"
				label="发生时间"
				show-overflow-tooltip
			/>
			<el-table-column
				prop="发生地点"
				label="发生地点"
				show-overflow-tooltip
			/>
			<el-table-column
				prop="车牌号"
				label="车牌号"
				show-overflow-tooltip
			/>
			<el-table-column prop="驾驶员" label="驾驶员" />
			<el-table-column prop="处理状态" label="处理状态" />
		</el-table>
		<!-- 分页器 
          :current-page="currentPage" 当前页码
          :page-size="limit" 每页显示条数
          :total="props.modalData.attrValues.length" 总条数
          @current-change="handleCurrentChange" 切换页码时触发
    -->
		<el-pagination
			size="small"
			background
			layout="prev, pager, next"
			:page-size="limit"
			:total="props.searchData.length"
			:current-page="currentPage"
			@current-change="handleCurrentChange"
		/>
	</el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, getCurrentInstance } from 'vue'
import * as XLSX from 'xlsx'
const { proxy } = getCurrentInstance()
const emits = defineEmits(['update:modeValue', 'ClearSource'])
//接收父组件传递过的isSHowDialog
const props = defineProps({
	modelValue: {
		type: Boolean,
		default: false,
	},
	searchData: {
		type: Array,
		default: [],
	},
})
//获取数据做一个映射
const accidentLevel = {
	1: '严重事故',
	2: '中等事故',
	3: '轻度事故',
	4: '轻微事故',
}
//处理状态
const handleStatus = {
	0: '待处理',
	1: '处理中',
	2: '已处理',
}
let map = null
onMounted(() => {
	map = proxy.$map
})
const dialogOverflowVisible = computed({
	get() {
		return props.modelValue
	},
	set(val) {
		//关闭查询结果弹窗,重置分页器 页码重置为1
		if (val == false) {
			//单项数据流 子组件的计算属性的set方法修改父组件的传递过来的值
			emits('update:modeValue', val)
		}
	},
})
/*********分页器逻辑*************/
const limit = 8 //每页显示条数
const currentPage = ref(1) //初始页码1
//改变页码事件回调
const handleCurrentChange = (value) => {
	currentPage.value = value
}

//表格数据用以下计算属性得到
const tableData = computed(() => {
	let result = props.searchData //用于存储搜索结果
	const start = (currentPage.value - 1) * 8
	const end = start + limit
	return result.slice(start, end).map((item) => {
		return {
			事件编号: item.values_.values_.事件编号,
			事件类型: item.values_.values_.事件类型,
			事件等级: accidentLevel[item.values_.values_.事件等级],
			发生时间: item.values_.values_.发生时间,
			发生地点: item.values_.values_.发生地点,
			车牌号: item.values_.values_.车牌号,
			驾驶员: item.values_.values_.驾驶员,
			处理状态: handleStatus[item.values_.values_.处理状态],
		}
	})
})
//点击每一行数据跳转到事故点
const flyToPoint = (事件编号) => {
	// let center = props.searchData.find(
	// 	(item) => item.values_.values_.事件编号 == 事件编号
	// ).getGeometry().flatCoordinates;
	let center = props.searchData.find(
		(item) => item.values_.values_.事件编号 == 事件编号
	).values_.geometry.flatCoordinates;
	map.getView().animate({
		center,
		zoom: 18,
		duration: 2000,
	})
}
let heatMapLayer = null
//添加热力图
const addHeatMap = () => {
	//如果存在热力图层就要移除它,并把热力图层设置为空,否则下一次点击无法生成新的热力图,
	if (heatMapLayer) {
		map.removeLayer(heatMapLayer)
		heatMapLayer = null
		return
	}
	//对查询到的每一条数据进行处理,添加权重属性 weight属性
	const heatFeatures = props.searchData.map((feature) => {
		feature.set('weight', feature.values_.values_.事件等级 * 0.25)
		return feature
	})
	heatMapLayer = new ol.layer.Heatmap({
		source: new ol.source.Vector({
			features: heatFeatures,
		}),
		//热力图配置
		biur: 10,
		//半径
		redius: 15,
		//权重 0-1 之间
		// 热力图的weight 要根据不同的事件设置不同的权重
		weight: function (feature) {
			return feature.get('weight')
		},
	})
	map.addLayer(heatMapLayer)
}
/****
 * 点击查看统计图触发函数
 * 1)获取事件数量
 * 2)显示隐藏统计图
 * 3)处理统计图数据--折现统计图数据
 * 4)处理统计图数据--饼图统计图数
 * *********/
let openChartValue = ref(false)
let eventCount = ref('')
let lineData = ref({}) //折现图数
let pieDataArr = ref([]) //饼图数据
//改变统计图
const changeOpenChart = () => {
	//1)获取事件数量
	eventCount.value = props.searchData.length
	//2)显示和隐藏
	openChartValue.value = !openChartValue.value
	//3)处理统计图数据--折线统计图
	const chartData = props.searchData.map((item) => {
		return item.values_.values_
	})
	// console.log("chartData",chartData);
	//循环12个月份,生成每个月份每个事情初始值为0的初始数据
	for (let i = 1; i <= 12; i++) {
		lineData.value[i + '月'] = {
			翻车: 0,
			刮擦: 0,
			碾压: 0,
			碰撞: 0,
			其他: 0,
			失火: 0,
		}
	}
	//  console.log("chartData",lineData.value);
	chartData.forEach((event) => {
		const timeStr = event.发生时间.split(' ')[0] // 获取拉框数据的所有时间
		const [year, month, day] = timeStr.split('.') //分割 年,月 日
		const monthStr = parseInt(month) + '月' //去掉个位数是前边的0
		lineData.value[monthStr][event.事件类型]++ //对[拉框数据]的月份和时间类型的对应数量进行累加
	})
	//4) 处理统计图数据--饼图数据
	let num1 = chartData.filter((item) => item.事件类型 == '翻车').length
	let num2 = chartData.filter((item) => item.事件类型 == '刮擦').length
	let num3 = chartData.filter((item) => item.事件类型 == '碾压').length
	let num4 = chartData.filter((item) => item.事件类型 == '碰撞').length
	let num5 = chartData.filter((item) => item.事件类型 == '其他').length
	let num6 = chartData.filter((item) => item.事件类型 == '失火').length
	pieDataArr.value = [num1, num2, num3, num4, num5, num6]
}
//统计图配置项--折现图堆叠
//这里的配置项是动态的,所以利用计算属性保持器响应性
const optionStackedLine = computed(() => {
	return {
		title: {
			text: `交通事件(${eventCount.value})起`,
		},
		tooltip: {
			trigger: 'axis',
		},
		legend: {
			data: ['翻车', '刮擦', '碾压', '碰撞', '其他', '失火'],
		},
		grid: {
			left: '3%',
			right: '4%',
			bottom: '3%',
			containLabel: true,
		},
		toolbox: {
			feature: {
				saveAsImage: {},
			},
		},
		xAxis: {
			type: 'category',
			boundaryGap: false,
			data: [
				'一月',
				'二月',
				'三月',
				'四月',
				'五月',
				'六月',
				'七月',
				'八月',
				'九月',
				'十月',
				'十一月',
				'十二月',
			],
		},
		yAxis: {
			type: 'value',
		},
		series: [
			{
				name: '翻车',
				type: 'line',
				stack: 'Total',
				data: [
					lineData.value['1月']['翻车'],
					lineData.value['2月']['翻车'],
					lineData.value['3月']['翻车'],
					lineData.value['4月']['翻车'],
					lineData.value['5月']['翻车'],
					lineData.value['6月']['翻车'],
					lineData.value['7月']['翻车'],
					lineData.value['8月']['翻车'],
					lineData.value['9月']['翻车'],
					lineData.value['10月']['翻车'],
					lineData.value['11月']['翻车'],
					lineData.value['12月']['翻车'],
				],
			},
			{
				name: '刮擦',
				type: 'line',
				stack: 'Total',
				data: [
					lineData.value['1月']['刮擦'],
					lineData.value['2月']['刮擦'],
					lineData.value['3月']['刮擦'],
					lineData.value['4月']['刮擦'],
					lineData.value['5月']['刮擦'],
					lineData.value['6月']['刮擦'],
					lineData.value['7月']['刮擦'],
					lineData.value['8月']['刮擦'],
					lineData.value['9月']['刮擦'],
					lineData.value['10月']['刮擦'],
					lineData.value['11月']['刮擦'],
					lineData.value['12月']['刮擦'],
				],
			},
			{
				name: '碾压',
				type: 'line',
				stack: 'Total',
				data: [
					lineData.value['1月']['碾压'],
					lineData.value['2月']['碾压'],
					lineData.value['3月']['碾压'],
					lineData.value['4月']['碾压'],
					lineData.value['5月']['碾压'],
					lineData.value['6月']['碾压'],
					lineData.value['7月']['碾压'],
					lineData.value['8月']['碾压'],
					lineData.value['9月']['碾压'],
					lineData.value['10月']['碾压'],
					lineData.value['11月']['碾压'],
					lineData.value['12月']['碾压'],
				],
			},
			{
				name: '碰撞',
				type: 'line',
				stack: 'Total',
				data: [
					lineData.value['1月']['碰撞'],
					lineData.value['2月']['碰撞'],
					lineData.value['3月']['碰撞'],
					lineData.value['4月']['碰撞'],
					lineData.value['5月']['碰撞'],
					lineData.value['6月']['碰撞'],
					lineData.value['7月']['碰撞'],
					lineData.value['8月']['碰撞'],
					lineData.value['9月']['碰撞'],
					lineData.value['10月']['碰撞'],
					lineData.value['11月']['碰撞'],
					lineData.value['12月']['碰撞'],
				],
			},
			{
				name: '其他',
				type: 'line',
				stack: 'Total',
				data: [
					lineData.value['1月']['其他'],
					lineData.value['2月']['其他'],
					lineData.value['3月']['其他'],
					lineData.value['4月']['其他'],
					lineData.value['5月']['其他'],
					lineData.value['6月']['其他'],
					lineData.value['7月']['其他'],
					lineData.value['8月']['其他'],
					lineData.value['9月']['其他'],
					lineData.value['10月']['其他'],
					lineData.value['11月']['其他'],
					lineData.value['12月']['其他'],
				],
			},
			{
				name: '失火',
				type: 'line',
				stack: 'Total',
				data: [
					lineData.value['1月']['失火'],
					lineData.value['2月']['失火'],
					lineData.value['3月']['失火'],
					lineData.value['4月']['失火'],
					lineData.value['5月']['失火'],
					lineData.value['6月']['失火'],
					lineData.value['7月']['失火'],
					lineData.value['8月']['失火'],
					lineData.value['9月']['失火'],
					lineData.value['10月']['失火'],
					lineData.value['11月']['失火'],
					lineData.value['12月']['失火'],
				],
			},
		],
	}
})
//统计图配置项--折线图堆叠
//这里的配置项是动态的,所以利用计算属性保持器响应性
const optionPie = computed(() => {
	return {
		title: {
			text: `交通事件(${eventCount.value})起`,
		},
		tooltip: {
			trigger: 'item',
		},
		legend: {
			orient: 'vertical',
			left: 'right',
		},
		series: [
			{
				name: '事件类型',
				type: 'pie',
				radius: '50%',
				data: [
					{ value: pieDataArr.value[0], name: '翻车' },
					{ value: pieDataArr.value[1], name: '刮擦' },
					{ value: pieDataArr.value[2], name: '碾压' },
					{ value: pieDataArr.value[3], name: '碰撞' },
					{ value: pieDataArr.value[4], name: '其他' },
					{ value: pieDataArr.value[5], name: '失火' },
				],
				emphasis: {
					itemStyle: {
						shadowBlur: 10,
						shadowOffsetX: 0,
						shadowColor: 'rgba(0, 0, 0, 0.5)',
					},
				},
			},
		],
	}
})
///* 两种统计图的切换显示 */
let isShowLine = ref(true) //默认先显示折线图
let isShowPie = ref(false)
//按月份统计
const changeLine = () => {
	if (!isShowLine.value) {
		isShowLine.value = true
		isShowPie.value = false
	}
}
//按类型统计
const changePie = () => {
	if (isShowLine.value) {
		isShowLine.value = false
		isShowPie.value = true
	}
}
//导出Excel
const exportExcel = () => {
	//创建工作簿
	const workbook = XLSX.utils.book_new()
	//将表格数据转换工作表
	const worksheet = XLSX.utils.json_to_sheet(tableData.value)
	//将工作表添加到工作簿
	XLSX.utils.book_append_sheet(workbook, worksheet, 'sheet1')
	//导出Excel文件
	XLSX.writeFile(workbook, 'table_data.xlsx')
}
const handleClose = () => {
	emits('ClearSource')
	// 关闭热力图图层
	heatMapLayer && heatMapLayer.getSource().clear()
	heatMapLayer = null
}
</script>

<style lang="scss" scoped>
.chart {
	width: 800px;
	height: 400px;
}
:deep(.el-table) {
	text-align: center;
}
:deep(.el-table__body tr .cell) {
	line-height: 13px;
}
</style>
